/**
 * 
 */
package com.wgo.precise.client.ui.view.delegates;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkbenchWindowActionDelegate;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.progress.IProgressService;

import remato.client.controller.ClientSession;
import remato.client.controller.ModelStatus;
import remato.client.controller.RequirementPlugin;
import remato.client.controller.exceptions.RematoClientException;
import remato.client.view.session.LoginDialog;
import remato.client.view.util.ReflectionHelper;
import remato.client.view.util.ReflectionRunnableWithProgress;
import remato.client.view.util.ViewerAction;

import com.wgo.precise.client.common.session.ISessionHolder;
import com.wgo.precise.client.common.session.PreciseSession;
import com.wgo.precise.client.common.session.PreciseSession.ObjectHolder;

/**
 * @author peide3
 *
 */
public class ImportXmlActionDelegate extends Action implements
		IWorkbenchWindowActionDelegate {

	private ImportXmlAction importXmlAction;
	
	/**
	 * @see org.eclipse.ui.IWorkbenchWindowActionDelegate#dispose()
	 */
	public void dispose() {
		importXmlAction.disposeSession();
		importXmlAction = null;
	}

	/**
	 * @see org.eclipse.ui.IWorkbenchWindowActionDelegate#init(org.eclipse.ui.IWorkbenchWindow)
	 */
	public void init(IWorkbenchWindow window) {
		importXmlAction = new ImportXmlAction(window);
	}

	/**
	 * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
	 */
	public void run(IAction action) {
		importXmlAction.run();
	}

	/**
	 * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, org.eclipse.jface.viewers.ISelection)
	 */
	public void selectionChanged(IAction action, ISelection selection) {}

}

class ImportXmlAction extends ViewerAction implements ISessionHolder<ClientSession> {

	private LoginDialog loginDialog;
	private FileDialog fileDialog;
	private PreciseSession session;
	
	public ImportXmlAction(IWorkbenchWindow window) {
		super("Import XML", PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_OBJS_WARN_TSK));
		init(window);
	}

    public void init(IWorkbenchWindow window) {
		fileDialog = new FileDialog(window.getShell(), SWT.OPEN);
		fileDialog.setFilterExtensions(new String[] { "*.xml" });
		fileDialog.setText("Select Precise file to import");
        loginDialog = new LoginDialog(window.getShell(),this, "Import XML", "Enter the url to the server targeted for the import.");
        setToolTipText("Import XML to server.");
    }

    @Override
    public void run() {
    	RequirementPlugin plugin = RequirementPlugin.getInstance();
    	if (plugin.isSessionSet()) {
    		if (plugin.getSession().isDirty()) {
    			MessageDialog dialog = new MessageDialog(RequirementPlugin.getInstance().getActiveShell(),
    					"Save existin session?", null, "You are currently logged in. Save unsaved changes?",
    					MessageDialog.QUESTION, new String[] {
    				IDialogConstants.OK_LABEL,
    				IDialogConstants.NO_LABEL,
    				IDialogConstants.CANCEL_LABEL }, 0);
    			switch (dialog.open()) {
    			case 0:
    				plugin.disposeSession(true);
    				break;
    			case 1:
    				plugin.disposeSession(false);
    				break;
    			case 2:
    				return;
    			}
    		} else {
    			plugin.disposeSession(false);
    		}
    	}
    	String fileName = fileDialog.open();
    	if (null == fileName) { //TODO: give an message?
    		super.run();
    		return;
    	}
    	File file = new File(fileName);
    	FileInputStream fileInputStream = null;
    	try {
			fileInputStream = new FileInputStream(file);
		} catch (FileNotFoundException e) {
			RequirementPlugin.logAndDisplay(new ModelStatus(IStatus.ERROR, "Error reading file.", e));
		}
		byte[] xmlFile = new byte[(int)file.length()];
		try {
			fileInputStream.read(xmlFile);
		} catch (IOException e) {
			RequirementPlugin.logAndDisplay(new ModelStatus(IStatus.ERROR, "Error reading file.", e));
		}
    	int result = loginDialog.open(); 
    	if (Window.OK == result) {
    		if (null != session) {
    			MessageDialog dialog = new MessageDialog(RequirementPlugin.getInstance().getActiveShell(),
    					"Really import data to database?", null, "This will replace all existing contents at '" + session.getServerContextUrl() + "'. Are you sure this is what you want?",
    					MessageDialog.QUESTION, new String[] {
    				IDialogConstants.OK_LABEL,
    				IDialogConstants.CANCEL_LABEL }, 0);
    			switch (dialog.open()) {
    			case 0:
    				
    				PreciseSession.ObjectHolder<Boolean> objectHolder = new PreciseSession.ObjectHolder<Boolean>();
    				IRunnableWithProgress op = new ReflectionRunnableWithProgress("Importing data from " + file.getAbsolutePath() + " to " + session.getServerContextUrl(), ReflectionHelper.retrieveMethod(getClass().getSimpleName(), session.getClass(), "importFromXml", byte[].class, ObjectHolder.class), session, xmlFile, objectHolder);
    				IProgressService progressService = PlatformUI.getWorkbench().getProgressService();
    				try {
						progressService.busyCursorWhile(op);
    				} catch (InvocationTargetException e) {
    					RequirementPlugin.logAndDisplay(new ModelStatus(IStatus.ERROR, "Error importing data from XML to DB.", e.getTargetException()));
    				} catch (InterruptedException e) {
    					RequirementPlugin.logAndDisplay(new ModelStatus(IStatus.ERROR, "Error importing data from XML to DB.", e));
    				}
    				break;
    			default:
    				return;
    			}
    		} else {
        		RequirementPlugin.log(new ModelStatus(IStatus.WARNING, PreciseSession.class.getSimpleName() + " was null."));
    		}
    	} else if (Window.CANCEL != result) {
    	}
    	super.run();
    }
    

	/* (non-Javadoc)
	 * @see remato.client.view.session.ISessionHolder#disposeSession()
	 */
	public boolean disposeSession() {
		session = null;
		return true;
	}

	/* (non-Javadoc)
	 * @see remato.client.view.session.ISessionHolder#disposeSession(boolean)
	 */
	public boolean disposeSession(boolean saveChanges) {
		return disposeSession();
	}

	/* (non-Javadoc)
	 * @see remato.client.view.session.ISessionHolder#disposeSession(java.lang.String)
	 */
	public boolean disposeSession(String whySaveExplanation) {
		return disposeSession();
	}

	/* (non-Javadoc)
	 * @see remato.client.view.session.ISessionHolder#getSession()
	 */
	public ClientSession getSession() {
		throw new RematoClientException(new ModelStatus(IStatus.ERROR, "Internal error, this method should never be called.", new IllegalStateException()));
	}

	/* (non-Javadoc)
	 * @see remato.client.view.session.ISessionHolder#setSession(remato.client.controller.ClientSession)
	 */
	public boolean setSession(PreciseSession newSession) {
		this.session = newSession;
		return true;
	}

	/* (non-Javadoc)
	 * @see remato.client.view.session.ISessionHolder#isSessionSet()
	 */
	public boolean isSessionSet() {
		return null != session;
	}
	
}